package org.openoa.engine.conf.config;

import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;

import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
import org.apache.hc.core5.http.io.SocketConfig;
import org.apache.hc.core5.ssl.SSLContextBuilder;
import org.apache.hc.core5.util.TimeValue;
import org.apache.hc.core5.util.Timeout;
import org.openoa.engine.vo.HttpClientProperties;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.BufferingClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.SSLContext;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;

@Configuration
public class RestTemplateConfig {

    @Bean
    RestTemplate restTemplate(@Qualifier("clientHttpRequestFactory") ClientHttpRequestFactory requestFactory, RestInterceptor restInterceptor) {
        // 使用BufferingClientHttpRequestFactory包装，允许多次读取响应体
        ClientHttpRequestFactory factory = requestFactory instanceof BufferingClientHttpRequestFactory
                ? requestFactory
                : new BufferingClientHttpRequestFactory(requestFactory);

        RestTemplate restTemplate = new RestTemplate(factory);

        // 设置UTF-8编码
        restTemplate.getMessageConverters()
                .stream()
                .filter(StringHttpMessageConverter.class::isInstance)
                .forEach(converter ->
                        ((StringHttpMessageConverter) converter).setDefaultCharset(StandardCharsets.UTF_8)
                );

        // 添加拦截器
        restTemplate.getInterceptors().add(restInterceptor);

        return restTemplate;
    }

    @Bean
    @ConfigurationProperties(prefix = "spring.resttemplate")
    HttpClientProperties httpClientProperties() {
        return new HttpClientProperties();
    }

    @Bean(name = "clientHttpRequestFactory")
    ClientHttpRequestFactory clientHttpRequestFactory(HttpClientProperties properties)
            throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {

        if (!properties.isUseHttpClientPool()) {
            // 不使用连接池的情况
            SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
            factory.setConnectTimeout(properties.getConnectTimeout());
            factory.setReadTimeout(properties.getReadTimeout());
            return factory;
        }

        // 创建SSL/TLS上下文
        SSLContext sslContext = SSLContextBuilder.create()
                .loadTrustMaterial((chain, authType) -> true) // 信任所有证书
                .build();

        // 设置Socket配置
        SocketConfig socketConfig = SocketConfig.custom()
                .setSoTimeout(Timeout.ofMilliseconds(properties.getReadTimeout()))
                .build();
        // 配置连接池
        PoolingHttpClientConnectionManager connectionManager =
                PoolingHttpClientConnectionManagerBuilder.create()
                        .setSSLSocketFactory(new SSLConnectionSocketFactory(
                                sslContext,
                                NoopHostnameVerifier.INSTANCE  // 跳过主机名校验
                        ))
                        .setDefaultSocketConfig(socketConfig)
                        .setMaxConnTotal(properties.getMaxTotalConnect())
                        .setMaxConnPerRoute(properties.getMaxConnectPerRoute())
                        .build();



        // 配置请求超时
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectionRequestTimeout(Timeout.ofMilliseconds(properties.getConnectionRequestTimeout()))
                .setResponseTimeout(Timeout.ofMilliseconds(properties.getReadTimeout()))
                .build();


        // 构建HttpClient
        CloseableHttpClient httpClient = HttpClients.custom()
                .setConnectionManager(connectionManager)
                .evictExpiredConnections()
                .setDefaultRequestConfig(requestConfig)
                .setKeepAliveStrategy((response, context) -> TimeValue.ofSeconds(5))
                .build();


        // 创建HttpComponentsClientHttpRequestFactory
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
        factory.setConnectTimeout(properties.getConnectTimeout());
        factory.setConnectionRequestTimeout(properties.getConnectionRequestTimeout());

        return factory;
    }
}
